package com.learn.springframework.v3.servlet;

import com.learn.springframework.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class HandlerAdapter {

    public boolean supports(Object handler) {
        return (handler instanceof HandlerMapping);
    }

    public ModelAndView handler(HttpServletRequest req, HttpServletResponse resp, HandlerMapping handler) throws Exception {


        // 把方法的形参列表和request的参数列表所在顺序进行一一对应
        Map<String, Integer> parameterMap = new HashMap<String, Integer>();
        // 提取方法中加了注解的参数
        Annotation[][] pa = handler.getMethod().getParameterAnnotations();
        for (int i = 0; i < pa.length; i++) {
            for (Annotation a : pa[i]) {
                if (a instanceof RequestParam) {
                    String paramName = ((RequestParam) a).value();
                    if (!"".equals(paramName.trim())) {
                        parameterMap.put(paramName, i);
                    }
                }
            }
        }

        // 提取方法中的request和response参数
        Class<?>[] parameterTypes = handler.getMethod().getParameterTypes();

        for (int i = 0; i < parameterTypes.length; i++) {
            Class<?> paramType = parameterTypes[i];
            if (paramType == HttpServletRequest.class || paramType == HttpServletResponse.class) {
                parameterMap.put(paramType.getName(), i);
            }
        }

        // 获得方法的形参列表
        Map<String, String[]> params = req.getParameterMap();
        // 实参列表
        Object[] paramValues = new Object[parameterTypes.length];
        for (Map.Entry<String, String[]> param : params.entrySet()) {
            String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "")
                    .replaceAll("\\s+", "");
            if (!parameterMap.containsKey(param.getKey())) {
                continue;
            }
            int index = parameterMap.get(param.getKey());
            paramValues[index] = caseStringValue(value, parameterTypes[index]);
        }

        if (parameterMap.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = parameterMap.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = req;
        }
        if (parameterMap.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = parameterMap.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = resp;
        }
        // TODO: 拿到null對象
        Object result = handler.getMethod().invoke(handler.getController(), paramValues);
        if (result == null || result instanceof Void) {
            return null;
        }
        boolean isModelAndView = handler.getMethod().getReturnType() == ModelAndView.class;
        if (isModelAndView) {
            return (ModelAndView) result;
        }
        return null;
    }

    private Object caseStringValue(String value, Class<?> parameterType) {
        if (String.class == parameterType) {
            return value;
        }
        // 如果是int
        // TODO: 待优化考虑使用策略模式
        if (Integer.class == parameterType) {
            return Integer.valueOf(value);
        } else if (Double.class == parameterType) {
            return Double.valueOf(value);
        }else {
            if (value != null) {
                return value;
            }
            return null;
        }

    }
}
